import math
import random
from collections import Counter


# 加载 Iris 数据集
def load_iris_data(filename='iris.data'):

    data = []
    try:
        with open(filename, 'r') as f:
            for line in f:
                if line.strip():  # 忽略空行
                    row = line.strip().split(',')
                    features = list(map(float, row[:-1]))  # 特征转换为浮点数
                    label = row[-1]  # 最后一列作为标签
                    data.append((features, label))
    except FileNotFoundError:
        print(f"Error: 文件 {filename} 未找到。")
        exit(1)
    return data


# 计算欧氏距离
def euclidean_distance(point1, point2):

    return math.sqrt(sum((x - y) ** 2 for x, y in zip(point1, point2)))


# KNN 分类算法
def knn_classify(train_data, test_point, k=3):

    distances = [(euclidean_distance(features, test_point), label) for features, label in train_data]
    distances.sort(key=lambda x: x[0])  # 按距离排序
    nearest_neighbors = distances[:k]
    labels = [label for _, label in nearest_neighbors]
    return Counter(labels).most_common(1)[0][0]  # 返回出现次数最多的标签


# 划分训练集和测试集
def train_test_split(data, test_size=0.2):

    random.shuffle(data)  # 打乱数据顺序
    split_index = int(len(data) * (1 - test_size))
    return data[:split_index], data[split_index:]


# 主函数
if __name__ == "__main__":
    # 加载数据并划分训练集和测试集
    data = load_iris_data()
    train_data, test_data = train_test_split(data)

    k = 3  # 可以通过命令行参数或其他方式设置
    correct_predictions = 0
    total_tests = len(test_data)

    # 对测试集中的每个样本进行预测，并统计准确率
    for features, true_label in test_data:
        predicted_label = knn_classify(train_data, features, k)
        if predicted_label == true_label:
            correct_predictions += 1

    accuracy = correct_predictions / total_tests
    print(f"KNN 分类准确率: {accuracy * 100:.2f}%")